package hn.cch.spring.core.annotation;

import hn.cch.spring.core.annotation.component.BeanImplement0;
import hn.cch.spring.core.annotation.component.BeanImplement1;
import hn.cch.spring.core.bean.BeanComponent;
import hn.cch.spring.core.bean.BeanDependencies;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Method;

public class AutowiredAnnotationDemo {

    private static final Logger logger = LoggerFactory.getLogger(AutowiredAnnotationDemo.class);


    public static void main(String[] args) throws NoSuchMethodException {
        // 测试AutowiredAnnotationBeanPostProcessor
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("beanDependencies", new BeanDependencies());
        beanFactory.registerSingleton("beanImplement0", new BeanImplement0());
        beanFactory.registerSingleton("beanImplement1", new BeanImplement1());

        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // ${}

        AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        beanPostProcessor.setBeanFactory(beanFactory);

        BeanComponent beanComponent = new BeanComponent();
        logger.info(beanComponent.toString());
        // beanPostProcessor.postProcessProperties(null, beanComponent, "beanComponent"); // // 执行依赖注入
        // log.info(beanComponent.toString());


        // // AutowiredAnnotationBeanPostProcessor.postProcessProperties方法执行过程
        // Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class
        //         .getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        // findAutowiringMetadata.setAccessible(true);
        // // 获取类中添加@Value和@Autowired注解的成员变量，方法参数信息
        // InjectionMetadata injectionMetadata = (InjectionMetadata) findAutowiringMetadata.invoke(
        //         beanPostProcessor, "beanComponent", BeanObject.class, null);
        // // InjectionMetadata.injectedElements
        // injectionMetadata.inject(beanComponent, "beanComponent", null); // 执行依赖注入
        // log.info(beanComponent.toString());


        // InjectionMetadata.inject方法执行过程
        // Field beanImplement0 = BeanObject.class.getDeclaredField("beanImplement0");
        // DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(beanImplement0, false);

        // Method setJavaHome = BeanObject.class.getDeclaredMethod("setJavaHome", String.class);
        // DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(new MethodParameter(setJavaHome, 0), true);

        Method setBeanDependencies = BeanComponent.class.getDeclaredMethod("setBeanDependencies", BeanDependencies.class);
        DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(new MethodParameter(setBeanDependencies, 0), true);

        Object object = beanFactory.doResolveDependency(dependencyDescriptor, null, null, null);
        assert object != null;
        logger.info(object.getClass().getName());
    }
}
